﻿using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Mathematics;
using FreeGoo.GameEngine.Renderables.Particles;

namespace FreeGoo.GameEngine.Renderables
{
    public class BodyRenderable : Renderable
    {
        private bool _isDeadly = false;
        public BodyRenderable(Geom geom)
            : base()
        {
            Geom = geom;

            geom.Tag = this;
            geom.Body.Tag = this;
            geom.CollisionCategories = Engine.StaticCollisionCategory;
            geom.CollidesWith = CollisionCategory.All;
        }

        public Body Body { get { return Geom.Body; } }
        public Geom Geom { get; protected set; }
        public override Vector2 Position { get { return Body.Position; } set { Body.Position = value; } }
        public override float Rotation { get { return Body.Rotation; } set { Body.Rotation = value; } }
        public bool IsDeadly
        {
            get
            {
                return _isDeadly;
            }

            set
            {
                if (_isDeadly != value)
                {
                    _isDeadly = value;
                    PrepareDeadlyCollissionCallback();
                    SignalStateChanged();
                }
            }
        }

        public override void UpdatePhysics()
        {
            base.UpdatePhysics();
            ScheduledForDelete =
                ScheduledForDelete ||
                Body.Position.X < -Engine.KillZone.X ||
                Body.Position.Y < -Engine.KillZone.Y ||
                Body.Position.X > Engine.Size.X + Engine.KillZone.X ||
                Body.Position.Y > Engine.Size.Y + Engine.KillZone.Y;

            if (ScheduledForDelete)
            {
            }
        }

        public override void AddToEngine(Engine engine)
        {
            base.AddToEngine(engine);
            engine.BodyRenderables.Add(this);

            AddToPhysicsSimulator();
        }

        public void AddToPhysicsSimulator()
        {
            Engine.PhysicsSimulator.Add(Body);
            Engine.PhysicsSimulator.Add(Geom);
        }

        public override void Delete()
        {
            base.Delete();
            Engine.BodyRenderables.Remove(this);

            RemoveFromPhysicsSimulator();
        }

        public void RemoveFromPhysicsSimulator()
        {
            Engine.PhysicsSimulator.Remove(Body);
            Engine.PhysicsSimulator.Remove(Geom);
        }

        public void PrepareDeadlyCollissionCallback()
        {
            if (_isDeadly)
            {
                Geom.OnCollision += DeadlyCollissionOccured;
            }
            else
            {
                Geom.OnCollision -= DeadlyCollissionOccured;
            }
        }

        private bool DeadlyCollissionOccured(Geom geometry1, Geom geometry2, ContactList contactList)
        {
            if (geometry1.Tag == null || !(geometry1.Tag is BodyRenderable) ||
                geometry2.Tag == null || !(geometry2.Tag is BodyRenderable))
            {
                return true;
            }

            BodyRenderable thisRenderable1 = geometry1.Tag as BodyRenderable;
            BodyRenderable otherRenderable2 = geometry2.Tag as BodyRenderable;

            if (this == otherRenderable2)
            {
                otherRenderable2 = thisRenderable1;
            }

            if (otherRenderable2 is Particle)
            {
                otherRenderable2.ScheduledForDelete = true;
            }

            return true;
        }
    }
}
